package com.vite.file.util;

import com.vite.common.config.ViteConfig;
import com.vite.common.exception.file.FileNameLengthLimitExceededException;
import com.vite.common.exception.file.FileSizeLimitExceededException;
import com.vite.common.exception.file.InvalidExtensionException;
import com.vite.common.utils.DateUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.Objects;

/**
 * x File Storage 工具类
 * <a href="https://x-file-storage.xuyanwu.cn/#/"/>
 * 后续可以拓展手动分片等功能
 */
public class XFileUtils {

    /**
     * 默认大小 50M
     */
    public static final long DEFAULT_MAX_SIZE = ViteConfig.getFileMaxSize() * 1024 * 1024;

    /**
     * 默认的文件名最大长度 100
     */
    public static final int DEFAULT_FILE_NAME_LENGTH = 100;

    /**
     *  验证文件是否验证条件
     *  @throws FileSizeLimitExceededException 如果超出最大大小
     *  @throws FileNameLengthLimitExceededException 文件名太长
     *  @throws InvalidExtensionException 文件校验异常
     */
    public static void validFile (MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        String filename = file.getOriginalFilename();
        //文件大小和格式验证
        assertNameLengthAllowed(filename);
        assertSizeAllowed(file, allowedExtension);
        assertMimeAllowed(filename, allowedExtension);
    }

    /**
     *  验证分片文件是否验证条件
     *  @throws FileNameLengthLimitExceededException 文件名太长
     *  @throws InvalidExtensionException 文件校验异常
     */
    public static void validPartFile (String fileName, String[] allowedExtension)
            throws FileNameLengthLimitExceededException,InvalidExtensionException
    {
        //文件大小和格式验证
        assertNameLengthAllowed(fileName);
        assertMimeAllowed(fileName, allowedExtension);
    }

    /**
     * 文件名长度校验
     *
     * @param fileName 文件名
     * @throws FileNameLengthLimitExceededException 如果超出最大大小
     */
    public static void assertNameLengthAllowed(String fileName)
            throws FileNameLengthLimitExceededException
    {
        //文件名长度验证
        int fileNameLength = Objects.requireNonNull(fileName).length();
        if (fileNameLength > DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(DEFAULT_FILE_NAME_LENGTH);
        }
    }

    /**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @throws FileSizeLimitExceededException 如果超出最大大小
     */
    public static void assertSizeAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException
    {
        if (file.getSize() > DEFAULT_MAX_SIZE)
        {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }
    }

    /**
     * 文件Mime类型校验
     *
     * @param fileName 文件名
     * @throws InvalidExtensionException 如果文件后缀名非法
     */
    public static void assertMimeAllowed( String fileName, String[] allowedExtension)
            throws InvalidExtensionException
    {
        String extension = getExtension(fileName);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION){
                throw new InvalidExtensionException.InvalidFileExtensionException(allowedExtension, extension,
                        fileName);
            }else{
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }
    }


    /**
     * 获取文件名的后缀
     *
     * @param fileName 文件名
     * @return 后缀名
     */
    public static String getExtension(String fileName)
    {
        return FilenameUtils.getExtension(fileName);
    }

    /**
     * 判断MIME类型是否是允许的MIME类型
     */
    public static boolean isAllowedExtension(String extension, String[] allowedExtension)
    {
        for (String str : allowedExtension)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件类型
     * <p>
     * 例如: 1.txt, 返回: txt
     *
     * @param fileName 文件名
     * @return 后缀（不含".")
     */
    public static String getFileType(String fileName)
    {
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0)
        {
            return "";
        }
        return fileName.substring(separatorIndex + 1).toLowerCase();
    }


    /**
     * 编码文件名
     */
    public static String getFileName(String fileName)
    {
        return String.format("%s_%s.%s",
                FilenameUtils.getBaseName(fileName), Seq.getId(), getExtension(fileName));
    }

    /**
     * 获取路径
     */
    public static String getPath()
    {
        return String.format("%s/", DateUtils.datePath());
    }

}
